﻿Option Strict On
Option Explicit On
Option Compare Text

Imports System.Drawing
Imports System.Text


Public Class ClickinUtil

    Private Const ERR_INVALID_POINT As String = "The following parameter value is not a valid coordinate: ""{0}"""

    ''' <summary>
    ''' This function will subtract Point2 coordinates from Point1 coordinates to form a new point
    ''' </summary>
    ''' <param name="point1"></param>
    ''' <param name="point2"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function SubtractPoints(ByVal point1 As Point, ByVal point2 As Point) As Point
        Return New Point((point1.X - point2.X), (point1.Y - point2.Y))
    End Function

    ''' <summary>
    ''' This function will add point coordinates together to form a new point
    ''' </summary>
    ''' <param name="point1"></param>
    ''' <param name="point2"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function AddPoints(ByVal point1 As Point, ByVal point2 As Point) As Point
        Return New Point((point1.X + point2.X), (point1.Y + point2.Y))
    End Function

    ''' <summary>
    ''' This utility function parses a string paramenter into a valid point
    ''' </summary>
    ''' <param name="pointParam"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function ConvertToPoint(ByVal pointParam As String) As Point
        Dim coord As New Point(0, 0)
        Dim points() As String

        points = pointParam.Split(Convert.ToChar(","))

        If (points.Count = 2) AndAlso (IsNumeric(points(0))) AndAlso (IsNumeric(points(1))) Then
            coord.X = Convert.ToInt32(points(0))
            coord.Y = Convert.ToInt32(points(1))
        Else
            'not a valid parameter
            Throw New ArgumentException(String.Format(ERR_INVALID_POINT, pointParam))
        End If

        Return coord
    End Function

    ''' <summary>
    ''' Adds a point to an actual point value to an instruction 
    ''' </summary>
    ''' <param name="instruction"></param>
    ''' <param name="pointParameter"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function AddToInstruction(ByVal instruction As Clickinator.Instruction, ByVal pointParameter As Point) As Clickinator.Instruction
        Dim ret As New Clickinator.Instruction
        Dim parameterValue As Point = New Point(0, 0)

        ret.Command = instruction.Command

        Try
            parameterValue = ConvertToPoint(instruction.Param)
            ret.Param = AddPoints(parameterValue, pointParameter).ToString
        Catch
            'an error occured just return the same parameter
            ret.Param = instruction.Param
        End Try

        'return new command
        Return ret
    End Function

    ''' <summary>
    ''' Adds an integer to an actual integer value to an instruction
    ''' </summary>
    ''' <param name="instruction"></param>
    ''' <param name="integerParameter"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function AddToInstruction(ByVal instruction As Clickinator.Instruction, ByVal integerParameter As Int32) As Clickinator.Instruction
        Dim ret As New Clickinator.Instruction
        Dim parameterValue As Int32 = Nothing

        ret.Command = instruction.Command
        If Int32.TryParse(instruction.Param, parameterValue) Then
            'conversion sucessful
            ret.Param = Convert.ToString(parameterValue + integerParameter)
        Else
            'not sucessful; return same thing
            ret.Param = instruction.Param
        End If

        Return ret
    End Function

    ''' <summary>
    ''' Converts an instruction list to it's string representation.
    ''' </summary>
    ''' <param name="instructions"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function InstructionListToString(ByVal instructions As List(Of Clickinator.Instruction)) As String
        Dim ret As New StringBuilder("")
        Dim singleInstruction As Clickinator.Instruction

        For Each singleInstruction In instructions
            ret.Append(singleInstruction.Command)
            ret.Append(Clickinator.InstructionSeparator)
            ret.AppendLine(singleInstruction.Param)
        Next

        Return ret.ToString
    End Function

    Public Shared Function ExtractDelimitedParameters(ByVal commandText As String, ByVal startDelemiter As String, ByVal endDelemiter As String) As List(Of String)

        Dim output As New List(Of String)
        Dim parameterStartIndex As Int32 = 0
        Dim parameterEndIndex As Int32 = 0

        'anticipated (first) read
        parameterStartIndex = commandText.IndexOf(startDelemiter, parameterStartIndex)
        parameterEndIndex = commandText.IndexOf(endDelemiter, parameterStartIndex + 1)

        'loop while there is a valid start and end index
        Do While ((parameterStartIndex > 0) AndAlso (parameterEndIndex > 0))
            'add string to array
            output.Add(commandText.Substring(parameterStartIndex, (parameterEndIndex - parameterStartIndex + 1)))

            'set start position for next read
            parameterStartIndex = parameterEndIndex + 1

            'get the next occurence of the start delemiter
            parameterStartIndex = commandText.IndexOf(startDelemiter, parameterStartIndex)

            'get the next occurence of the end delemiter
            parameterEndIndex = commandText.IndexOf(endDelemiter, parameterStartIndex + 1)
        Loop

        Return output
    End Function

End Class
